﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using ShootSearch.Core;
using ShootSearch.Util.Serializers;
using System.IO;
using System.Diagnostics;
using ShootSearch.Util;
using ShootSearch.Runner.Configurations;
using log4net;
using ShootSearch.Logging;

namespace ShootSearch.Runner.Controls
{
    public class FormMainControl
    {
        FormMain form = null;
        ListView listViewTasks;
        TaskListConfig listConfig;
        ILog logger;
        Task task = null;
        MethodCaller buttonActivateCaller;
        MethodCaller logCaller;

        public FormMainControl(FormMain form)
        {
            this.form = form;
            this.listViewTasks = form.listViewTasks;
            logger = log4net.LogManager.GetLogger("MainForm");
            buttonActivateCaller = new MethodCaller(ButtonActivate);
            logCaller = new MethodCaller(FlushStatus);
            Log.Info(logger, "Program launched");
        }

        #region Save Load
        public void LoadTasks()
        {
            listConfig = TaskListConfig.Load();
            for (int i = 0; i < listConfig.Tasks.Count; i++)
            {
                TaskConfig tc = TaskConfig.Load(IO.FormatDirName(listConfig.Tasks[i].Path) + Task.TAKS_CONFIG);
                if (tc != null)
                {
                    Task_Add(tc, IO.FormatDirName(listConfig.Tasks[i].Path));
                }
            }
        }

        public void SaveTasks()
        {
            listConfig = new TaskListConfig();
            for (int i = 0; i < listViewTasks.Items.Count; i++)
            {
                Task tc = listViewTasks.Items[i].Tag as Task;
                if (tc != null)
                {
                    listConfig.Tasks.Add(new TaskItem(tc.Config.ContextPath));
                }
            }
            listConfig.Save();
        } 
        #endregion

        public void ButtonActivate()
        {
            task = GetTask();
            JobStatus status = JobStatus.Stopping;
            if (task != null)
            {
                status = task.Status;
                FlushStatus();
                form.labelStatus.Text = "Task: " + task.Config.ContextPath;
            }
            else
            {
                form.timerUpdateTask.Enabled = false;
                form.labelStatus.Text = string.Empty;

            }

            switch (status)
            { 
                case JobStatus.Running:
                    form.tsButtonDelete.Enabled = false;
                    form.tsButtonRun.Enabled = false;
                    form.tsButtonStop.Enabled = true;
                    form.tsButtonConfig.Enabled = false;

                    if (!form.timerUpdateTask.Enabled)
                    {
                        form.timerUpdateTask.Enabled = true;
                    }

                    if (task != null)
                    {
                        listViewTasks.SelectedItems[0].ImageIndex = 1;
                        listViewTasks.SelectedItems[0].Group = listViewTasks.Groups[1];

                    }
                    break;

                case JobStatus.Stopping:
                case JobStatus.Completing:
                    form.tsButtonDelete.Enabled = false;
                    form.tsButtonRun.Enabled = false;
                    form.tsButtonStop.Enabled = false;
                    form.tsButtonConfig.Enabled = false;

                    if (!form.timerUpdateTask.Enabled && task != null)
                    {
                        form.timerUpdateTask.Enabled = true;
                    }
                    break;
                case JobStatus.Unstarted:
                    SetButtonUnstarted();
                    if (task != null)
                    {
                        listViewTasks.SelectedItems[0].ImageIndex = 0;
                        listViewTasks.SelectedItems[0].Group = listViewTasks.Groups[0];

                    }
                    break;
                case JobStatus.Stopped:
                    SetButtonUnstarted();
                    if (task != null)
                    {
                        listViewTasks.SelectedItems[0].ImageIndex = 2;
                        listViewTasks.SelectedItems[0].Group = listViewTasks.Groups[2];

                    }
                    break;
                case JobStatus.Completed:
                    SetButtonUnstarted();
                    if (task != null)
                    {
                        listViewTasks.SelectedItems[0].ImageIndex = 3;
                        listViewTasks.SelectedItems[0].Group = listViewTasks.Groups[3];

                    }                 
                    break;
            }



        }

        protected void SetButtonUnstarted()
        {
            form.tsButtonDelete.Enabled = true;
            form.tsButtonRun.Enabled = true;
            form.tsButtonStop.Enabled = false;
            form.tsButtonConfig.Enabled = true;
            form.timerUpdateTask.Enabled = false;
        }

        #region Button_Task Functions

        public void Task_New()
        {
            FormNewTask taskForm = new FormNewTask();
            TaskConfig tc = EditTaskConfig(taskForm);
            Task_New_Add(tc, taskForm.GetContextPath());
        }

        private void Task_New_Add(TaskConfig tc, string contextPath)
        {
            if (tc != null)
            {
                Task_Add(tc, contextPath);
            }

            if (tc.Task != null && tc.LaunchType == LaunchType.AutomaticallyOnce)
            {
                tc.Task.Start();
            }
        }


        public void Task_OpenImport(bool isOpen)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (isOpen)
            {
                ofd.Filter = "Task Configuration|" + Task.TAKS_CONFIG;
            }
            else
            {
                ofd.Filter = "Task Configuration|*.config;*.xml";
            }
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                TaskConfig tc = TaskConfig.Load(ofd.FileName);
                if (tc == null)
                {
                    MessageBox.Show("This is not a legal task configuration file");
                }

                if (isOpen)
                {
                    FileInfo fi = new FileInfo(ofd.FileName);
                    Task_New_Add(tc, fi.Directory.FullName);
                }
                else
                {
                    FormNewTask taskForm = new FormNewTask();
                    taskForm.ImportTask(tc);
                    tc = EditTaskConfig(taskForm);
                    if (tc != null)
                    {
                        Task_Add(tc, taskForm.GetContextPath());
                    }
                }
            }
        }

        public void Task_Delete()
        {
            if (listViewTasks.SelectedItems.Count == 0) return;
            if (MessageBox.Show("Delete?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
                == DialogResult.Yes)
            {
                int itemIndex = listViewTasks.SelectedItems[0].Index;
                Task task = GetTask();
                if (task != null) task.Stop();
                task.StatusChanged -= new EventHandler(Task_StatusChanged);
                try
                {
                    Directory.Delete(task.Config.ContextPath, true);
                }
                catch (Exception ex)
                {
                    Log.Warn(logger, "Remove error!", ex);
                }
                listViewTasks.Items.RemoveAt(itemIndex);
            }

        }

        public void Task_Run()
        {
            if (task != null)
            {
                task.Start();
                ButtonActivate();
            }
        }

        public void Task_Stop()
        {
            if (task != null)
            {
                task.Stop();
                ButtonActivate();
            }
        }

        public void Task_Edit()
        {
            if (task != null &&
                (task.Status == JobStatus.Completed ||
                task.Status == JobStatus.Stopped ||
                task.Status == JobStatus.Unstarted))
            {
                FormNewTask taskForm = new FormNewTask();
                taskForm.LoadTaskConfig(task.Config);
                TaskConfig tc = EditTaskConfig(taskForm);
                if (tc != null)
                {
                    task.Config = tc;
                }

                if (task.Config.LaunchType == LaunchType.AutomaticallyAlways)
                {
                    task.Start();
                }
                
            }
        }

        private static TaskConfig EditTaskConfig(FormNewTask taskForm)
        {
            TaskConfig taskConfig = null;
            if (taskForm.ShowDialog() == DialogResult.OK)
            {
                taskConfig = taskForm.GetTaskConfig();
                XmlFormatter.ToXmlFile(taskConfig, taskForm.GetContextPath() + TaskConfig.TASKFILE);
                
            }
            taskForm.Dispose();

            return taskConfig;
        } 

        #endregion

        #region Menu_Task Functions
        public void Task_OpenPath()
        {
            if (task != null)
            {
                Process.Start(task.Config.ContextPath);
            }
        }

        public void Task_Reload()
        {
            if (task != null &&
                (task.Status == JobStatus.Completed ||
                task.Status == JobStatus.Stopped ||
                task.Status == JobStatus.Unstarted))
            {
                TaskConfig taskConfig = TaskConfig.Load(IO.FormatDirName(task.Config.ContextPath) + TaskConfig.TASKFILE);
                if (taskConfig != null)
                {
                    task.Config = taskConfig;
                }
            }
        }
        #endregion

        public void Form_Visibility_Changed()
        {
            if (form.Visible)
            {
                form.tsmiIconSysHide.Text = "&Hide";
            }
            else
            {
                form.tsmiIconSysHide.Text = "&Show";
            }            
        }

        public void ChangeHideShow()
        {
            if (form.Visible)
            {
                form.Hide();
            }
            else
            {
                form.Show();
            }            
        }

        public void Exit()
        {
            if (MessageBox.Show("Exit?","Question",MessageBoxButtons.YesNo, MessageBoxIcon.Question) 
                == DialogResult.Yes)
            {
                SaveTasks();
                form.Hide();
                form.Close();
                form.Dispose();
                Application.Exit();
            }
        }

        public void Timer_ShowTaskStatus()
        {
            //if (task != null)
            //{
            //    FlushStatus();
            //}
        }

        protected void Task_Add(TaskConfig tc, string xmlPath)
        {
            if (tc != null)
            {
                Task newTask = new Task();
                newTask.Config = tc;
                newTask.StatusChanged += new EventHandler(Task_StatusChanged);
                newTask.MessageLogged += new log4net.Appender.MessageLoggedEventHandler(Task_MessageLogged);
                ListViewItem item = new ListViewItem(new string[]
                {
                    newTask.Config.TaskName,
                    xmlPath
                });
                item.ImageIndex = 0;
                item.Tag = newTask;
                item.Group = listViewTasks.Groups[0];
                listViewTasks.Items.Add(item);

                if (newTask.Config.LaunchType == LaunchType.AutomaticallyAlways)
                {
                    newTask.Start();
                }
            }
        }

        protected void Task_MessageLogged(object sender, log4net.Appender.MessageLoggedEventArgs e)
        {
            if (task != null && sender as Task == task)
            {
                try
                {
                    form.Invoke(logCaller);
                }
                catch (Exception ex)
                {
                    Log.Warn(logger, "Invoke error!", ex);
                }
            

                //FlushStatus();
            }
        }

        private void Task_StatusChanged(object sender, EventArgs e)
        {
            try
            {
                form.Invoke(buttonActivateCaller);
            }
            catch (Exception ex)
            {
                Log.Warn(logger, "Invoke error!", ex);
            }
            
        }

        private void FlushStatus()
        {
            form.textBoxStatus.Text = task.StatusSummary;
            string text = task.LogMsg;
            if (text.Length != form.textBoxLogs.Text.Length)
            {
                form.textBoxLogs.Text = text;
                form.textBoxLogs.SelectionStart = text.Length;
                form.textBoxLogs.SelectionLength = 0;
                form.textBoxLogs.ScrollToCaret();

            }
        }

        protected Task GetTask()
        {
            if (listViewTasks.SelectedItems.Count == 0) return null;
            ListViewItem item = listViewTasks.SelectedItems[0];
            return item.Tag as Task;
        }
     
    }
}
